package sync

import (
	"sync"
	"sync/atomic"
	"unsafe"
)

var expunged = unsafe.Pointer(new(interface{}))

type Map struct {
	mu sync.Mutex
	// 原子操作无需加锁（读，删除，改都直接操作）
	read atomic.Value

	// 非原子操作加锁
	// 用于新增是存储
	dirty map[interface{}]*entry
}

type entry struct {
	p unsafe.Pointer
}

type readOnly struct {
	m map[interface{}]*entry
	// 存在脏数据，miss需要回源
	amended bool
}

func (m *Map) Store(key, value interface{}) {
	read, _ := m.read.Load().(readOnly)
	// read存在，服用空间存储
	if e, ok := read.m[key]; ok && e.tryStore(&value) {
		return
	}
	// 加锁
	// 最后一次确认read当中没有，如果有 entry复用，数值存入
	// 没有，如果dirty内有，则直接覆盖内容
	// 否则
	// read是否脏了，不脏
	// 拷入dirty 因为update是不更新dirty
	// read 标示为脏
	// 数据写入
	// 解锁
}

func (m *Map) Delete(key interface{}) {
	read, _ := m.read.Load().(readOnly)
	e, ok := read.m[key]
	if !ok && read.amended {
		// 加锁，删除
	} else {
		e.delete()
	}
}

func (e *entry) delete() (hadValue bool) {
	for {
		p := atomic.LoadPointer(&e.p)
		if p == nil || p == expunged {
			return false
		}
		if atomic.CompareAndSwapPointer(&e.p, p, nil) {
			return true
		}
	}
}

func (e *entry) tryStore(i *interface{}) bool {
	for {
		p := atomic.LoadPointer(&e.p)
		if p == expunged {
			return false
		}
		if atomic.CompareAndSwapPointer(&e.p, p, unsafe.Pointer(i)) {
			return true
		}
	}
}
